import {Menu} from "./Menu";
import {TimeOut} from "./TimeOut";
import * as fs from "fs";
import * as path from "path";
import {ExpressExt} from "./ExpressExt";
import {Log} from "./Log";
var chokidar = require('chokidar');

export class HotReload {

    static watcher:fs.FSWatcher;
    /**
     * 所有监视目录
     */
    static menus:Array<string> = [];

    /**
     * 启动热更新
     * @param watch 监视的目录
     */
    static start(watch:Array<string>) {
        if (HotReload.watcher)
            return;

        HotReload.menus = watch;

        HotReload.watcher = chokidar.watch(watch, {
            ignored: /[\/\\]\./,
            persistent: true,
            awaitWriteFinish: true,
            ignoreInitial: true,
        });
        let watcher = HotReload.watcher;

        
        for (let m of ExpressExt.allRoute) {
            watcher.add(path.join(Menu.root, m.router.menu))
        }
        watcher.on('change', (path, stats) => {
            // console.log(`File ${path} changed size to ${stats.size}`);
            HotReload.reLoadFile(path);
        });

        watcher.on('add', (path, stats) => {
            // console.log(`File ${path} add size to ${stats.size}`);
            HotReload.reLoadFile(path);
        });
    }

    private static reloadTime = "";

    private static reLoadFile(menu:string) {
        if (! menu.endsWith(".js"))
            return;

        // console.log(`reLoadFile ${path}`);
        HotReload.cleanCache(menu)

        if (HotReload.reloadTime.length > 0) {
            TimeOut.remove(HotReload.reloadTime);
        }
        HotReload.reloadTime = TimeOut.add(500, ()=> {

            //清空监视目录缓存
            HotReload.menus.forEach(it=> {
                fs.readdirSync(it).forEach((file)=> {
                    if ( file.endsWith(".js")) {
                        try {
                            HotReload.cleanCache(path.join(it, file));
                        } catch (e) {
                            Log.err(e);
                        }
                    }
                });
            })

            ExpressExt.reloadRoutes();
        })
    }

    static cleanCache(modulePath:string) {
        //console.error("cleanCache : " + modulePath);
        var module = require.cache[modulePath];

        // remove reference in module.parent
        if (module) {
            if (module.parent) {
                let ii = module.parent.children.indexOf(module);
                if (ii >= 0)
                    module.parent.children.splice(ii, 1);
            }
        }
        delete require.cache[modulePath];
    }
}